/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jmodcog2.fwd;

import jmodcog2.base.BaseRunner;
import jmodcog2.fwd.config.NetConfig;

/**
 *
 * @author Mitch
 */
public abstract class BiasNet extends Net {
    //

    protected final boolean biased;
    protected final boolean shared_bias;
    //protected final float[] bias_conns;
    //
    //

    public BiasNet(NetConfig config) {
        super(config);
        this.biased = config.isBiased();
        this.shared_bias = config.hasSharedBias();
    }

    protected void _fwd(int layer_j, int node_j) {
        float sum = 0;
        int node_i = 0;
        int ci = -1;
        while (node_i < num_nodes[layer_j] - 1) {
            ci = _conn_index(layer_j - 1, node_i, node_j);
            if (ci >= 0) {
                sum += _get_conn_weight(ci)
                        * _get_node(_node_index(layer_j - 1, node_i));
            }
            node_i += 1;
        }

        if (biased) {
            sum += _get_bias(_bias_index(layer_j, node_j));
        }

        nodes[_node_index(layer_j, node_j)] = _f(sum);
    }

    protected int _bias_index(int layer_j, int node_j) {
        if (shared_bias) {
            return layer_j - 1;
        } else {
            return _node_index(layer_j, node_j);
        }
    }

    protected abstract float _get_bias(int index);

    protected abstract void _set_bias(int index, float val);

    protected abstract void _add_bias(int index, float val);

    protected void forward() {
        setMode(FWD);
        for (byte j = 1; j < num_layers; j++) {
            setLayer(j);
            execute(num_nodes[j]);
        }
    }

    @Override
    public boolean process(float[] input) {
        if (setInput(input)) {
            copyIn();
            forward();
            copyOut();
            return true;
        }
        return false;
    }
    static final int FWD = 0x0002;

    @Override
    protected void _run(int mode) {
        super._run(mode);
        if (mode == FWD) {
            int layer = LAYER[0];
            if (layer < num_layers && layer > 0) {
                int node = getGlobalId(0);
                if (node < num_nodes[layer]) {
                    _fwd(layer, node);
                }
            }
        }
    }
}
